package ar.edu.caece.compiler.grammar.factories;

import ar.edu.caece.compiler.grammar.AbstractTokenVisitorFactory;
import ar.edu.caece.compiler.grammar.Recognizer;
import ar.edu.caece.compiler.grammar.TokenRecognizer;
import ar.edu.caece.compiler.grammar.TokenVisitor;
import ar.edu.caece.compiler.grammar.attributes.Attribute;
import ar.edu.caece.compiler.grammar.attributes.ListaParametrosAttribute;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeExpr;
import ar.edu.caece.compiler.grammar.attributes.tree.NodeParametrosFuncion;
import ar.edu.caece.compiler.grammar.nonterminals.EXPR;
import ar.edu.caece.compiler.grammar.nonterminals.OTROSA;
import ar.edu.caece.compiler.grammar.nonterminals.PASOPAM1;


public class PASOPAM1Factory extends AbstractTokenVisitorFactory {

	private static PASOPAM1Factory INSTANCE;
	
	public static PASOPAM1Factory getInstance() throws Exception {
		if(INSTANCE==null) INSTANCE = new PASOPAM1Factory();
		return INSTANCE;
	}
	
	private EXPRFactory exprFactory;
	private OTROSAFactory otrosaFactory;
	private TokenVisitor parseEXPR;
	private TokenVisitor parseOTROSA;
	
	private Initializer initializer = new Initializer() {
		
		@Override
		public void init() throws Exception {
			initializer = NoOperationInitializer.getInstance();
			exprFactory = EXPRFactory.getInstance();
			otrosaFactory = OTROSAFactory.getInstance();
			parseOTROSA = otrosaFactory.makeVisitor();
			parseEXPR = exprFactory.makeVisitor();
		}
	};
	
	private PASOPAM1Factory() throws Exception {

	}
	
	@Override
	public TokenVisitor makeChainedVisitor(
			final TokenVisitor siguiente) throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador)
					throws Exception {			
				TokenVisitor parseEXPR2 = exprFactory.makeChainedVisitor(siguiente);
				parseEXPR2.addInheritedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parseEXPR2.addInheritedAttribute(Attribute.LISTA_PARAMETROS_HEREDADA, getAttribute(Attribute.LISTA_PARAMETROS_HEREDADA));
				parseEXPR2.addInheritedAttribute(Attribute.ARBOL_HEREDADO, getAttribute(Attribute.ARBOL_HEREDADO));
				
				Recognizer result = llamador.execute(parseEXPR2);
				if(result instanceof EXPR) {
					NodeParametrosFuncion nodeLlamada = (NodeParametrosFuncion) getAttribute(Attribute.ARBOL_HEREDADO);

					parseOTROSA.addInheritedAttribute(Attribute.LISTA_PARAMETROS_HEREDADA,getAttribute(Attribute.LISTA_PARAMETROS_HEREDADA));
					parseOTROSA.addInheritedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
					
					EXPR expr = (EXPR) result;
					
					nodeLlamada.addParametro((NodeExpr) expr.getAttribute(Attribute.ARBOL_SINTETIZADO));
					parseOTROSA.addInheritedAttribute(Attribute.ARBOL_HEREDADO, nodeLlamada);					
					
					OTROSA otrosa = (OTROSA) nextToken().execute(parseOTROSA);
					PASOPAM1 pasopam1 = new PASOPAM1 (expr, otrosa);
					pasopam1.addAttribute(Attribute.LISTA_PARAMETROS_SINTETIZADA, otrosa.getAttribute(Attribute.LISTA_PARAMETROS_SINTETIZADA));
					
					pasopam1.addAttribute(Attribute.ARBOL_SINTETIZADO, otrosa.getAttribute(Attribute.ARBOL_SINTETIZADO));

					
					return pasopam1;
				} 
				else {
					return result;
				}
			}
			
		};
	
	}
	@Override
	public TokenVisitor makeVisitor() throws Exception {
		initializer.init();

		return new TokenVisitor() {

			@Override
			public Recognizer defaultCase(TokenRecognizer llamador) throws Exception {
				NodeParametrosFuncion nodeLlamada = (NodeParametrosFuncion) getAttribute(Attribute.ARBOL_HEREDADO);
				parseEXPR.addInheritedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				parseEXPR.addInheritedAttribute(Attribute.LISTA_PARAMETROS_HEREDADA, getAttribute(Attribute.LISTA_PARAMETROS_HEREDADA));
				parseEXPR.addInheritedAttribute(Attribute.ARBOL_HEREDADO, getAttribute(Attribute.ARBOL_HEREDADO));
				
				parseOTROSA.addInheritedAttribute(Attribute.LISTA_PARAMETROS_HEREDADA,getAttribute(Attribute.LISTA_PARAMETROS_HEREDADA));
				parseOTROSA.addInheritedAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA,getAttribute(Attribute.TABLA_SIMBOLOS_HEREDADA));
				
				EXPR expr = (EXPR) llamador.execute(parseEXPR);
				
				nodeLlamada.addParametro((NodeExpr) expr.getAttribute(Attribute.ARBOL_SINTETIZADO));
				parseOTROSA.addInheritedAttribute(Attribute.ARBOL_HEREDADO, nodeLlamada);
				
				OTROSA otrosa = (OTROSA) nextToken().execute(parseOTROSA);
				PASOPAM1 pasopam1 = new PASOPAM1 (expr, otrosa);
				pasopam1.addAttribute(Attribute.LISTA_PARAMETROS_SINTETIZADA, otrosa.getAttribute(Attribute.LISTA_PARAMETROS_SINTETIZADA));
				
				pasopam1.addAttribute(Attribute.ARBOL_SINTETIZADO, otrosa.getAttribute(Attribute.ARBOL_SINTETIZADO));

				
				return pasopam1;
			}
		};
	}
	
	
}
